﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace Noris.Schedule.Support.Services
{
	// DEKLARACE interface a args PRO SLUŽBY TYPU "FUNKCE"
	#region INTERFACE IFunctionMenuItem : předpis pro položku menu, které se nabízí na elementu grafu
	/// <summary>
	/// Interface, který předepisuje vlastnosti programu, který vytváří položku menu, které se nabízí na elementu grafu.
	/// </summary>
	public interface IFunctionMenuItem
	{
		/// <summary>
		/// Systém se ptá poskytovatele, zda chce pro daný element nabídnout svoji funkci.
		/// Tato metoda se volá jen při prvním zobrazování menu.
		/// Poskytovatel se rozhodne podle typu grafu, typu elementu a třídy řádku a elementu.
		/// V tuto chvíli není znám konkrétní element. rozhodnutí platí pro všechny obdobné elementy grafu.
		/// Pro danou kombinaci se systém ptá jen jednou, odpověď platí pro všechny stejné řádky a elementy.
		/// Pro konkrétní řádek a element lze pouze řídit Enabled/Disabled položky menu, a to metodou IsMenuItemEnabledFor().
		/// Pro aktivaci používání metody IsMenuItemEnabledFor() je třeba zde nastavit args.EnabledStateDependingOnElement = true;.
		/// </summary>
		/// <param name="args">Specifikace situace, která nastala, a pro kterou systém hledá nabídku funkcí. 
		/// Do tohoto argumentu by měla tato metoda vepsat popisek menu, pokud jej chce nabízet.</param>
		/// <returns></returns>
		bool IsFunctionSuitableFor(FunctionMenuItemSuitableArgs args);
		/// <summary>
		/// Metoda je volaná před každým zobrazením menu, a to jen pro providery kteří o to požádali.
		/// Tato žádost se vyjadřuje nastavením args.EnabledStateDependingOnElement = true; v metodě IsFunctionSuitableFor().
		/// Metoda vrací true, pokud se její menu má zobrazit jako Enabled.
		/// V tuto chvíli jsou přesně známy údaje o místě kliknutí, o konkrétním elementu i o dalších vybraných elementech.
		/// </summary>
		/// <param name="args"></param>
		/// <returns></returns>
		bool IsMenuItemEnabledFor(FunctionMenuItemRunArgs args);
		/// <summary>
		/// Vstupní metoda do výkonné části pluginu
		/// </summary>
		/// <param name="args"></param>
		void Run(FunctionMenuItemRunArgs args);
	}
	#endregion
	#region CLASS FunctionMenuItemKey : SPECIFIKACE MENU (typ grafu, typ prostoru, typ elementu, datová třída)
	/// <summary>
	/// Třída popisuje příležitost, pro kterou se hledají vhodná menu.
	/// Pokud konkrétní provider chce v dané situaci nabídnout svoje menu, pak nastaví jeho vlastnosti a vrátí true.
	/// </summary>
	public struct FunctionMenuItemKey
	{
		#region KONSTRUKCE
		/// <summary>
		/// Konstruktor
		/// </summary>
		/// <param name="graphMode">Typ grafu</param>
		/// <param name="menuKind">Prostor, kde se kliklo</param>
		/// <param name="elementDrawType">Druh elementu</param>
		/// <param name="rowClassNumber">Číslo třídy řádku</param>
		/// <param name="elementClassNumber">Číslo třídy elementu</param>
		public FunctionMenuItemKey(RowGraphMode graphMode, FunctionMenuItemAreaType menuKind, GraphElementShapeType elementShapeType, int rowClassNumber, int elementClassNumber)
		{
			this._GraphMode = graphMode;
			this._AreaType = menuKind;
			this._ElementShapeType = elementShapeType;
			this._RowClassNumber = rowClassNumber;
			this._ElementClassNumber = elementClassNumber;
		}
		#endregion
		#region PROMĚNNÉ
		private RowGraphMode _GraphMode;
		private FunctionMenuItemAreaType _AreaType;
		private GraphElementShapeType _ElementShapeType;
		private int _RowClassNumber;
		private int _ElementClassNumber;
		#endregion
		#region OVERRIDES
		public override string ToString()
		{
			return "{RowGraph=" + this.GraphMode + "; RowClass=" + this.RowClassNumber + "; AreaType=" + this.AreaType + "; ElementDraw=" + this.ElementShapeType + "}";
		}
		public override int GetHashCode()
		{
			return this.GraphModeInt ^ this.AreaTypeInt ^ this.ElementShapeTypeInt ^ this.RowClassNumber ^ this.ElementClassNumber;
		}
		public override bool Equals(object obj)
		{
			if (obj is FunctionMenuItemKey)
			{
				FunctionMenuItemKey other = (FunctionMenuItemKey)obj;
				return (this._GraphMode == other._GraphMode &&
					this._AreaType == other._AreaType &&
					this._ElementShapeType == other._ElementShapeType &&
					this._RowClassNumber == other._RowClassNumber &&
					this._ElementClassNumber == other._ElementClassNumber);
			}
			return false;
		}
		private int GraphModeInt { get { return (int)this._GraphMode; } }
		private int AreaTypeInt { get { return (int)this._AreaType; } }
		private int ElementShapeTypeInt { get { return (int)this._ElementShapeType; } }
		#endregion
		#region PROPERTY
		/// <summary> { get; }
		/// Typ grafu v aktuálním řádku
		/// </summary>
		public RowGraphMode GraphMode { get { return this._GraphMode; } }
		/// <summary> { get; }
		/// Typ prostoru, kam uživatel kliknul
		/// </summary>
		public FunctionMenuItemAreaType AreaType { get { return this._AreaType; } }
		/// <summary> { get; }
		/// Číslo třídy řádku
		/// </summary>
		public int RowClassNumber { get { return this._RowClassNumber; } }
		/// <summary> { get; }
		/// Číslo třídy elementu
		/// </summary>
		public int ElementClassNumber { get { return this._ElementClassNumber; } }
		/// <summary> { get; }
		/// Tvar elementu.
		/// </summary>
		public GraphElementShapeType ElementShapeType { get { return this._ElementShapeType; } }
		#endregion
	}
	#endregion
	#region CLASS FunctionMenuItemSuitableArgs : ZÍSKÁNÍ INFORMACÍ O MENU: URČENÍ TEXTU MENU A ZATŘÍDĚNÍ DO SKUPINY
	/// <summary>
	/// FunctionMenuItemSuitableArgs : Třída, pomocí které se provider vyjadřuje ke konkrétní situaci, zda chce nabízet svoje menu.
	/// </summary>
	public class FunctionMenuItemSuitableArgs
	{
		#region KONSTRUKCE
		public FunctionMenuItemSuitableArgs(FunctionMenuItemKey menuKey)
		{
			this._MenuKey = menuKey;
		}
		#endregion
		#region PROPERTY
		/// <summary> { get; }
		/// Typ grafu v aktuálním řádku
		/// </summary>
		public RowGraphMode KeyGraphMode { get { return this._MenuKey.GraphMode; } }
		/// <summary> { get; }
		/// Typ prostoru, kam uživatel kliknul
		/// </summary>
		public FunctionMenuItemAreaType KeyAreaType { get { return this._MenuKey.AreaType; } }
		/// <summary> { get; }
		/// Číslo třídy řádku
		/// </summary>
		public int KeyRowClassNumber { get { return this._MenuKey.RowClassNumber; } }
		/// <summary> { get; }
		/// Číslo třídy elementu
		/// </summary>
		public int KeyElementClassNumber { get { return this._MenuKey.ElementClassNumber; } }
		/// <summary> { get; }
		/// Tvar elementu.
		/// </summary>
		public GraphElementShapeType KeyElementShapeType { get { return this._MenuKey.ElementShapeType; } }
		/// <summary> { get; set; }
		/// Kompletně sestavená položka menu.
		/// Pokud funkce chce, může jí sestavit včetně všech parametrů, a takto bude položka zobrazována.
		/// </summary>
		public ToolStripItem MenuItem { get; set; }
		/// <summary> { get; set; }
		/// Text menu
		/// </summary>
		public string MenuCaption { get; set; }
		/// <summary> { get; set; }
		/// Obrázek v menu
		/// </summary>
		public Image MenuImage { get; set; }
		/// <summary> { get; set; }
		/// Text ToolTipu
		/// </summary>
		public string MenuToolTipText { get; set; }
		/// <summary> { get; set; }
		/// Příznak, že položka menu může měnit svůj stav podle stavu elementu, na kterém je menu zavoláno.
		/// Pokud ano, pak před zobrazením menu je volána metoda IFunctionMenuItem.GetMenuItemEnabledFor() s předáním informací o aktuálním elementu.
		/// </summary>
		public bool EnabledStateDependingOnElement { get; set; }
		/// <summary> { get; set; }
		/// Příznak, že položka menu má mít sub-položky, viz this.MenuSubItemsCaption
		/// </summary>
		public bool MenuHasSubItems { get; set; }
		/// <summary> { get; set; }
		/// Text menu podpoložek menu.
		/// Klíč v Dictionary je klíčem podpoložky.
		/// Value v Dictionary je zobrazovaný text.
		/// Podpoložky mají Images v MenuSubItemsImage.
		/// </summary>
		public Dictionary<string, string> MenuSubItemsCaption { get; set; }
		/// <summary> { get; set; }
		/// Text menu podpoložek menu.
		/// Klíč v Dictionary je klíčem podpoložky.
		/// Value v Dictionary je Image pro položku menu.
		/// </summary>
		public Dictionary<string, Image> MenuSubItemsImage { get; set; }
		/// <summary> { get; set; }
		/// Skupina menu. Pokud chceme mít svoje položky menu pohromadě, pak sem vložíme unikátní název skupiny. 
		/// Hodnotou MenuOrder zajistíme třídění položek v rámci skupiny.
		/// </summary>
		public string MenuGroup { get; set; }
		/// <summary> { get; set; }
		/// Pořadí položky menu v rámci její skupiny MenuGroup.
		/// </summary>
		public int MenuOrder { get; set; }
		#endregion
		#region PROMĚNNÉ
		private FunctionMenuItemKey _MenuKey;
		#endregion
	}
	#endregion
	#region
	public class FunctionMenuItemRunArgs
	{
		#region KONSTRUKCE
		/// <summary>
		/// Konstruktor
		/// </summary>
		/// <param name="graphMode">Typ grafu</param>
		/// <param name="menuKind">Prostor, kde se kliklo</param>
		/// <param name="elementDrawType">Druh elementu</param>
		/// <param name="rowClassNumber">Číslo třídy řádku</param>
		/// <param name="elementClassNumber">Číslo třídy elementu</param>
		public FunctionMenuItemRunArgs(RowGraphMode graphMode, FunctionMenuItemAreaType menuKind, GraphElementShapeType elementShapeType, DataPointerStr clickedItem, IDataSource dataSource)
		{
			this._GraphMode = graphMode;
			this._AreaType = menuKind;
			this._ElementShapeType = elementShapeType;
			this._ClickedItem = clickedItem;
			this._SelectedElements = null;
			this._DataSource = dataSource;
		}
		#endregion
		#region PROMĚNNÉ
		private RowGraphMode _GraphMode;
		private FunctionMenuItemAreaType _AreaType;
		private GraphElementShapeType _ElementShapeType;
		private DataPointerStr _ClickedItem;
		private List<DataPointerStr> _SelectedElements;
		private IDataSource _DataSource;
		#endregion
		#region PROPERTY
		/// <summary> { get; }
		/// Typ grafu v aktuálním řádku
		/// </summary>
		public RowGraphMode GraphMode { get { return this._GraphMode; } }
		/// <summary> { get; }
		/// Typ prostoru, kam uživatel kliknul
		/// </summary>
		public FunctionMenuItemAreaType AreaType { get { return this._AreaType; } }
		/// <summary> { get; }
		/// Pointer na řádek a element, na kterém došlo ke kliknutí
		/// </summary>
		public DataPointerStr ClickedItem { get { return this._ClickedItem; } }
		/// <summary> { get; }
		/// Tvar elementu.
		/// </summary>
		public GraphElementShapeType ElementShapeType { get { return this._ElementShapeType; } }
		/// <summary>
		/// Datový zdroj grafu
		/// </summary>
		public IDataSource DataSource { get { return this._DataSource; } }
		/// <summary>
		/// Seznam aktuálně vybraných elementů. Nikdy není null.
		/// </summary>
		public List<DataPointerStr> SelectedElements
		{
			get
			{
				if (this._SelectedElements == null)
					this._SelectedElements = new List<DataPointerStr>();
				return this._SelectedElements;
			}
			set { this._SelectedElements = value; } }
		#endregion
	}
	#endregion
	#region ENUM FunctionMenuItemAreaType : místo v grafu, kam člověk kliknul
	/// <summary>
	/// Druh objektu, na který uživatel kliknul
	/// </summary>
	public enum FunctionMenuItemAreaType
	{
		/// <summary>
		/// Prázdný řádek v grafu mezi elementy
		/// </summary>
		EmptyRow,
		/// <summary>
		/// Textová část grafu, některý sloupec
		/// </summary>
		TextItem,
		/// <summary>
		/// Záhlaví řádku (vlevo v řádku)
		/// </summary>
		RowHeader,
		/// <summary>
		/// Záhlaví sloupce (nahoře)
		/// </summary>
		ColumnHeader,
		/// <summary>
		/// Prvek grafu, element
		/// </summary>
		GraphElement
	}
	#endregion
}
